昨天聊過 Task.WhenAll , 得知其底層就是等待多個 Task 完成的機制, 那 Task 到底是甚麼呢 ?
Task類別代表不會傳回值,而且通常會以非同步方式執行的單一作業。 Task 物件是工作架構 非同步模式 的其中一個核心元件,第一次是在 .NET Framework 4 中引進。 由於物件所執行的工作 Task 通常會線上程集區執行緒上以非同步方式執行,而不是在主應用程式執行緒上同步執行,因此您可以使用 Status 屬性以及 IsCanceled 、 IsCompleted 和 IsFaulted 屬性來判斷工作的狀態。 最常見的情況是使用 lambda 運算式來指定工作要執行的工作。
以上是微軟文件裡的說法, 這段敘述其實並不能說服我, 所以我打算從另一個角度是著揭開它的神秘面紗。 接下來對 Task 的探索可能會更為凌亂, 但我想探索底層就如同瞎子摸象, 每一次都摸一點點, 換個角度再摸一點點, 當累積足夠, 就可以真正了解大象的模樣。
public class Task : IThreadPoolWorkItem, IAsyncResult, IDisposable
可以看見繼承自三種物件, 其中 IAsyncResult
放了一些變數, 比較簡單之後遇到順口提即可。
IDisposable
是釋放資源相關, 跟同步非同步沒太大關連。
我們把焦點放在 IThreadPoolWorkItem
, Task 其實簡單點說, 就是 IThreadPoolWorkItem
的封裝。
進入 IThreadPoolWorkItem
可以看到, 他就是一個介面, 讓人可以把 something 送入 TP ( threadPool )
// Interface to something that can be queued to the TP. This is implemented by
// QueueUserWorkItemCallback, Task, and potentially other internal types.
// For example, SemaphoreSlim represents callbacks using its own type that
// implements IThreadPoolWorkItem.
//
// If we decide to expose some of the workstealing
// stuff, this is NOT the thing we want to expose to the public.
//
internal interface IThreadPoolWorkItem
{
[SecurityCritical]
void ExecuteWorkItem();
[SecurityCritical]
void MarkAborted(ThreadAbortException tae);
}
向下一層查看裡面兩個方法
[SecurityCritical]
public void ExecuteWorkItem()
{
m_action.Invoke(m_completingTask);
}
[SecurityCritical]
public void MarkAborted(ThreadAbortException tae)
{
/* NOP */
}
發現 MarkAborted
為空, 跳過, 以 ExecuteWorkItem
為主
其中兩個變數 m_action
和 m_completingTask
都是在 FinishContinuations()
中設定的, 這裡偷偷超進度說一下, 該函數會在 Task 的某階段變化時調用, 所以整個流程就是
FinishContinuations
會把待完成任務設置進 threadPoolIThreadPoolWorkItem
中的 ExecuteWorkItem
就會執行該任務值得一說的是, 這並不是唯一一條 Task 設置非同步任務進 TP ,與觸發 TP 中任務的路線。
而且在此刻我們沒有真的看到 TP 的資料結構, 按照第二天的文章, 其想必也會是個 lock-free data structure 吧。
透過閱讀 FinishContinuations
來了解以下兩個問題
明天見!